package pikes.samples.countries;

import java.util.Locale;
import java.util.Properties;

import org.springframework.config.java.annotation.Bean;
import org.springframework.config.java.annotation.ExternalBean;
import org.springframework.context.MessageSource;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.ThemeResolver;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver;
import org.springframework.web.servlet.theme.CookieThemeResolver;
import org.springframework.web.servlet.theme.ThemeChangeInterceptor;
import org.springframework.web.servlet.view.BeanNameViewResolver;

import pikes.html.xhtml.XHTMLPage;
import pikes.html.xhtml.version10.StrictDocType;
import pikes.samples.countries.CountryService;
import pikes.samples.countries.ui.CountriesController;
import pikes.samples.countries.ui.CountriesExcelView;
import pikes.samples.countries.ui.CountriesPdfView;
import pikes.samples.countries.ui.ErrorsController;
import pikes.samples.countries.ui.peak.ConfigPage;
import pikes.samples.countries.ui.peak.DetailPage;
import pikes.samples.countries.ui.peak.ErrorPage;
import pikes.samples.countries.ui.peak.HomePage;
import pikes.samples.countries.ui.peak.MainPage;
import pikes.xml.PrettyPrintingConfiguration;
import pikes.xml.XMLFormattingConfiguration;

public abstract class CountriesViewConfiguration {

	@Bean
	public MessageSource messageSource() {
		ResourceBundleMessageSource bean = new ResourceBundleMessageSource();
		bean.setBasename("messages");
		return bean;
	}

	@Bean
	public ViewResolver viewResolver() {
		return new BeanNameViewResolver();
	}

	@Bean
	public XMLFormattingConfiguration prettyPrint() {
		PrettyPrintingConfiguration formatting = new PrettyPrintingConfiguration();

		formatting.setExpandEmptyTag(true);
		formatting.setNewLine(true);
		formatting.setIndenting(true);

		return formatting;
	}

	private void configurePage(XHTMLPage page) {
		page.setFormat(prettyPrint());
		page.setDocType(new StrictDocType());
	}

	@Bean
	public View homeView() {
		HomePage page = new HomePage();

		configurePage(page);

		return page;
	}

	@Bean
	public View configView() {
		ConfigPage page = new ConfigPage();

		configurePage(page);

		return page;
	}

	@Bean
	public View countries_mainView() {
		MainPage page = new MainPage();

		configurePage(page);

		return page;
	}

	@Bean
	public View countries_detailView() {
		DetailPage page = new DetailPage();

		configurePage(page);

		return page;
	}

	@Bean
	public View countries_excelView() {
		return new CountriesExcelView();
	}

	@Bean
	public View countries_pdfView() {
		return new CountriesPdfView();
	}

	@Bean
	public View errorHttp404View() {
		ErrorPage page = new ErrorPage();

		configurePage(page);

		return page;
	}

	@Bean
	public LocaleResolver localeResolver() {
		CookieLocaleResolver localeResolver = new CookieLocaleResolver();
		localeResolver.setDefaultLocale(Locale.US);
		return localeResolver;
	}

	@Bean
	public HandlerInterceptor localeChangeInterceptor() {
		return new LocaleChangeInterceptor();
	}

	@Bean
	public ThemeResolver themeResolver() {
		CookieThemeResolver themeResolver = new CookieThemeResolver();

		themeResolver.setDefaultThemeName("spring");

		return themeResolver;
	}

	@Bean
	public HandlerInterceptor themeChangeInterceptor() {
		return new ThemeChangeInterceptor();
	}

	@Bean
	public HandlerMapping urlMapping() {
		SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();

		handlerMapping
				.setInterceptors(new HandlerInterceptor[] { localeChangeInterceptor(), themeChangeInterceptor() });

		Properties mappings = new Properties();
		mappings.put("/home.htm", countriesController());
		mappings.put("/config.htm", countriesController());
		mappings.put("/copy.htm", countriesController());
		mappings.put("/main/home.htm", countriesController());
		mappings.put("/main/detail.htm", countriesController());
		mappings.put("/main/countries.xls", countriesController());
		mappings.put("/main/countries.pdf", countriesController());
		mappings.put("/notfound.htm", errorsController());

		handlerMapping.setMappings(mappings);

		return handlerMapping;
	}

	@Bean
	public Controller countriesController() {
		CountriesController bean = new CountriesController();

		PropertiesMethodNameResolver methodNameResolver = new PropertiesMethodNameResolver();

		Properties mappings = new Properties();
		mappings.put("/home.htm", "handleHome");
		mappings.put("/config.htm", "handleConfig");
		mappings.put("/copy.htm", "handleCopy");
		mappings.put("/main/home.htm", "handleMain");
		mappings.put("/main/detail.htm", "handleDetail");
		mappings.put("/main/countries.xls", "handleExcel");
		mappings.put("/main/countries.pdf", "handlePdf");

		methodNameResolver.setMappings(mappings);

		bean.setMethodNameResolver(methodNameResolver);

		bean.setCountryService(countryService());

		return bean;
	}

	@Bean
	public Controller errorsController() {
		ErrorsController bean = new ErrorsController();

		PropertiesMethodNameResolver methodNameResolver = new PropertiesMethodNameResolver();

		Properties mappings = new Properties();
		mappings.put("/notfound.htm", "handleHttp404");

		methodNameResolver.setMappings(mappings);

		bean.setMethodNameResolver(methodNameResolver);

		return bean;
	}

	@ExternalBean
	public abstract CountryService countryService();
}


